package edu.rit.drh4818.raytracing.util;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import edu.rit.drh4818.raytracing.light.PointLight;
import edu.rit.drh4818.raytracing.object.ObjectProperties;
import edu.rit.drh4818.raytracing.object.Plane;
import edu.rit.drh4818.raytracing.object.SceneObject;
import edu.rit.drh4818.raytracing.object.Sphere;
import edu.rit.drh4818.raytracing.shaders.*;
import edu.rit.drh4818.raytracing.shaders.lighting.PhongShader;
import edu.rit.drh4818.raytracing.shaders.procedural.*;
import edu.rit.drh4818.raytracing.tone.*;

/**
 * All of the non-general information about the scene.
 * 
 * @author Darren Headrick
 *
 */
public class Scene 
{
	/**
	 * 
	 */
	public static final Scene instance = new Scene();
	
	/**
	 * The eye coordinates.
	 */
	public double eyex, eyey, eyez;
	
	/**
	 * The screen bounds.
	 */
	public int screenX, screenY, screenZ;
	
	/**
	 * Background color.
	 */
	public Color background;
	
	/**
	 * Make shadows go through transparent objects.
	 */
	public boolean softShadows = true;
	
	/**
	 * Maximum depth.
	 */
	public int MAX_DEPTH = 40;
	
	/**
	 * List of all objects.
	 */
	public List<SceneObject> objects = new ArrayList<SceneObject>();
	
	/**
	 * List of all lights.
	 */
	public List<PointLight> lights = new ArrayList<PointLight>();
	
	/**
	 * Flags to enable/disable supersampling.
	 */
	public boolean SUPERSAMPLING = false,
					SUPERSAMPLING_MIRROR = false;
	
	/**
	 * Scene shader.
	 */
	public Shader sceneShader =  new Illuminate( new PhongShader() );
	
	/**
	 * Tone reproduction;
	 */
	//public ToneReproduction tone = new Ward(1000, 100);
	//public ToneReproduction tone = new Reinhard(1, 100);
	public ToneReproduction tone = null;
	
	static 
	{
		// choose the scene background color
		Scene.instance.background = Color.CYAN;
		
		// The light source
		Scene.instance.lights.add( new PointLight( 450, -500, -5000, Color.WHITE ) );
		
		// The clear ball.
		ObjectProperties prop = new ObjectProperties();
		prop.ambient = prop.diffuse = prop.specular = Color.WHITE;
		prop.ka = prop.kd = .075F; prop.ks = .2F; prop.ke = 20F;
		prop.kr = .01F; prop.kt = .85F; prop.n = .95F;
		Scene.instance.objects.add( new Sphere( 350, 240, 150, 120, prop ));
	
		// The mirror ball.
		prop = new ObjectProperties();
		prop.ambient =  prop.diffuse = new Color( .7F, .7F, .7F ); 
		prop.specular = Color.WHITE;
		prop.ka = .15F; prop.kd = .25F; prop.ks = 1F; prop.ke = 20F;
		prop.kr = .75F; prop.kt = 0;
		Scene.instance.objects.add( new Sphere( 200, 330, 550, 130, prop ));
		
		// the tiled plane.
		prop = new ObjectProperties();
		prop.diffuse = prop.specular = Color.WHITE;
		prop.ka = prop.kd = .5F;
		prop.shader = new TiledShader( Color.RED, Color.YELLOW, 400, 2000 );
		Scene.instance.objects.add( new Plane( -1199, 1599, 900, prop ) );
		
		// screen coordinates
		Scene.instance.screenZ = 0; Scene.instance.screenX = 600; Scene.instance.screenY = 500;
		
		// eye coordinates
		Scene.instance.eyez = -2000; Scene.instance.eyex = 300; Scene.instance.eyey = 250;
	}
}